Türkçe

Şema Birleştirme ile GraphQL Federasyonunun gücünü keşfedin. Ölçeklenebilirliği ve sürdürülebilirliği artırarak birden çok servisten birleşik bir GraphQL API'si oluşturmayı öğrenin.

GraphQL Federasyonu: Şema Birleştirme (Schema Stitching) - Kapsamlı Bir Rehber

Sürekli gelişen modern uygulama geliştirme dünyasında, ölçeklenebilir ve sürdürülebilir mimarilere olan ihtiyaç çok önemli hale gelmiştir. Mikroservisler, doğal modülerlikleri ve bağımsız dağıtılabilirlikleri ile popüler bir çözüm olarak ortaya çıkmıştır. Ancak, çok sayıda mikroservisi yönetmek, özellikle istemci uygulamalarına birleşik bir API sunma konusunda karmaşıklıklara yol açabilir. İşte bu noktada GraphQL Federasyonu ve özellikle Şema Birleştirme (Schema Stitching) devreye giriyor.

GraphQL Federasyonu Nedir?

GraphQL Federasyonu, birden çok temel GraphQL servisinden (genellikle mikroservisleri temsil eder) tek, birleşik bir GraphQL API'si oluşturmanıza olanak tanıyan güçlü bir mimaridir. Geliştiricilerin farklı servislerdeki verileri tek bir grafmış gibi sorgulamasına olanak tanır, bu da istemci deneyimini basitleştirir ve istemci tarafında karmaşık orkestrasyon mantığına olan ihtiyacı azaltır.

GraphQL Federasyonu için iki temel yaklaşım vardır:

Bu makale, kavramlarını, faydalarını, sınırlamalarını ve pratik uygulamasını keşfederek Şema Birleştirme (Schema Stitching) üzerine odaklanmaktadır.

Şema Birleştirmeyi Anlamak

Şema Birleştirme, birden çok GraphQL şemasını tek ve uyumlu bir şemada birleştirme işlemidir. Bu birleşik şema, temel servislerin karmaşıklığını istemciden gizleyen bir cephe (facade) görevi görür. Bir istemci birleştirilmiş şemaya bir istekte bulunduğunda, ağ geçidi isteği akıllıca uygun temel servise/servislere yönlendirir, verileri alır ve sonuçları istemciye döndürmeden önce birleştirir.

Şöyle düşünebilirsiniz: Her biri farklı mutfaklarda uzmanlaşmış birden fazla restoranınız (servisleriniz) var. Şema Birleştirme, her restorandaki tüm yemekleri birleştiren evrensel bir menü gibidir. Bir müşteri (istemci) evrensel menüden sipariş verdiğinde, sipariş akıllıca uygun restoran mutfaklarına yönlendirilir, yemek hazırlanır ve ardından müşteri için tek bir teslimatta birleştirilir.

Şema Birleştirmedeki Anahtar Kavramlar

Şema Birleştirmenin Faydaları

Şema Birleştirme, mikroservis mimarisini benimseyen kuruluşlar için birçok cazip fayda sunar:

Şema Birleştirmenin Sınırlamaları

Şema Birleştirme çok sayıda avantaj sunsa da, sınırlamalarının farkında olmak önemlidir:

Şema Birleştirmenin Pratik Uygulaması

Node.js ve graphql-tools kütüphanesini (şema birleştirme için popüler bir seçim) kullanarak Şema Birleştirmenin nasıl uygulanacağına dair basitleştirilmiş bir örnek üzerinden geçelim. Bu örnek, iki mikroservisi içerir: bir Kullanıcı Servisi ve bir Ürün Servisi.

1. Uzak Şemaları Tanımlayın

İlk olarak, her bir uzak servis için GraphQL şemalarını tanımlayın.

Kullanıcı Servisi (user-service.js):


const { buildSchema } = require('graphql');

const userSchema = buildSchema(`
  type User {
    id: ID!
    name: String
    email: String
  }

  type Query {
    user(id: ID!): User
  }
`);

const users = [
  { id: '1', name: 'Alice Smith', email: 'alice@example.com' },
  { id: '2', name: 'Bob Johnson', email: 'bob@example.com' },
];

const userRoot = {
  user: (args) => users.find(user => user.id === args.id),
};

module.exports = {
  schema: userSchema,
  rootValue: userRoot,
};

Ürün Servisi (product-service.js):


const { buildSchema } = require('graphql');

const productSchema = buildSchema(`
  type Product {
    id: ID!
    name: String
    price: Float
    userId: ID!  # Kullanıcı Servisine yabancı anahtar
  }

  type Query {
    product(id: ID!): Product
  }
`);

const products = [
  { id: '101', name: 'Laptop', price: 1200, userId: '1' },
  { id: '102', name: 'Smartphone', price: 800, userId: '2' },
];

const productRoot = {
  product: (args) => products.find(product => product.id === args.id),
};

module.exports = {
  schema: productSchema,
  rootValue: productRoot,
};

2. Ağ Geçidi Servisini Oluşturun

Şimdi, iki şemayı bir araya getirecek olan ağ geçidi servisini oluşturun.

Ağ Geçidi Servisi (gateway.js):


const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeRemoteExecutableSchema } = require('@graphql-tools/wrap');
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const { introspectSchema } = require('@graphql-tools/wrap');
const { printSchema } = require('graphql');
const fetch = require('node-fetch');

async function createRemoteSchema(uri) {
  const fetcher = async (params) => {
    const response = await fetch(uri, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(params),
    });
    return response.json();
  };

  const schema = await introspectSchema(fetcher);
  return makeRemoteExecutableSchema({
    schema,
    fetcher,
  });
}

async function main() {
  const userSchema = await createRemoteSchema('http://localhost:4001/graphql');
  const productSchema = await createRemoteSchema('http://localhost:4002/graphql');

  const stitchedSchema = stitchSchemas({
    subschemas: [
      { schema: userSchema },
      { schema: productSchema },
    ],
    typeDefs: `
      extend type Product {
        user: User
      }
    `,
    resolvers: {
      Product: {
        user: {
          selectionSet: `{ userId }`,
          resolve(product, args, context, info) {
            return info.mergeInfo.delegateToSchema({
              schema: userSchema,
              operation: 'query',
              fieldName: 'user',
              args: {
                id: product.userId,
              },
              context,
              info,
            });
          },
        },
      },
    },
  });

  const app = express();
  app.use('/graphql', graphqlHTTP({
    schema: stitchedSchema,
    graphiql: true,
  }));

  app.listen(4000, () => console.log('Ağ Geçidi sunucusu http://localhost:4000/graphql üzerinde çalışıyor'));
}

main().catch(console.error);

3. Servisleri Çalıştırın

Kullanıcı Servisini ve Ürün Servisini farklı portlarda çalıştırmanız gerekecektir. Örneğin:

Kullanıcı Servisi (port 4001):


const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./user-service');

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: rootValue,
  graphiql: true,
}));

app.listen(4001, () => console.log('Kullanıcı servisi http://localhost:4001/graphql üzerinde çalışıyor'));

Ürün Servisi (port 4002):


const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./product-service');

const app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: rootValue,
  graphiql: true,
}));

app.listen(4002, () => console.log('Ürün servisi http://localhost:4002/graphql üzerinde çalışıyor'));

4. Birleştirilmiş Şemayı Sorgulayın

Artık birleştirilmiş şemayı ağ geçidi üzerinden (port 4000'de çalışan) sorgulayabilirsiniz. Şunun gibi bir sorgu çalıştırabilirsiniz:


query {
  product(id: "101") {
    id
    name
    price
    user {
      id
      name
      email
    }
  }
}

Bu sorgu, ID'si "101" olan ürünü alır ve ayrıca ilişkili kullanıcıyı Kullanıcı Servisinden getirir, bu da Şema Birleştirmenin tek bir istekte birden çok servisteki verileri nasıl sorgulamanıza olanak tanıdığını gösterir.

Gelişmiş Şema Birleştirme Teknikleri

Temel örneğin ötesinde, Şema Birleştirme uygulamanızı geliştirmek için kullanılabilecek bazı gelişmiş teknikler şunlardır:

Şema Birleştirme ve Apollo Federation Arasında Seçim Yapmak

Şema Birleştirme, GraphQL Federasyonu için geçerli bir seçenek olsa da, Apollo Federation gelişmiş özellikleri ve iyileştirilmiş geliştirici deneyimi nedeniyle daha popüler bir seçenek haline gelmiştir. İşte iki yaklaşımın bir karşılaştırması:

Özellik Şema Birleştirme Apollo Federation
Şema Tanımı Mevcut GraphQL şema dilini kullanır Direktiflerle bildirimsel bir şema dili kullanır
Sorgu Planlama Manuel sorgu delegasyonu gerektirir Apollo Gateway tarafından otomatik sorgu planlama
Tür Uzantıları Sınırlı destek Tür uzantıları için yerleşik destek
Anahtar Direktifleri Desteklenmiyor Varlıkları tanımlamak için @key direktifini kullanır
Dağıtık İzleme Manuel uygulama gerektirir Dağıtık izleme için yerleşik destek
Araçlar ve Ekosistem Daha az olgun araçlar Daha olgun araçlar ve geniş bir topluluk
Karmaşıklık Büyük sistemlerde yönetimi karmaşık olabilir Büyük ve karmaşık sistemler için tasarlanmıştır

Ne Zaman Şema Birleştirme Seçilmeli:

Ne Zaman Apollo Federation Seçilmeli:

Gerçek Dünya Örnekleri ve Kullanım Durumları

İşte Şema Birleştirme de dahil olmak üzere GraphQL Federasyonunun nasıl kullanılabileceğine dair bazı gerçek dünya örnekleri:

Şema Birleştirme İçin En İyi Uygulamalar

Başarılı bir Şema Birleştirme uygulaması sağlamak için şu en iyi uygulamaları izleyin:

Sonuç

Şema Birleştirme ile GraphQL Federasyonu, bir mikroservis mimarisinde birden çok servisten birleşik API'ler oluşturmak için güçlü bir yaklaşım sunar. Temel kavramlarını, faydalarını, sınırlamalarını ve uygulama tekniklerini anlayarak, veri erişimini basitleştirmek, ölçeklenebilirliği artırmak ve sürdürülebilirliği geliştirmek için Şema Birleştirmeden yararlanabilirsiniz. Apollo Federation daha gelişmiş bir çözüm olarak ortaya çıkmış olsa da, Şema Birleştirme daha basit senaryolar veya mevcut GraphQL servislerini entegre ederken geçerli bir seçenek olmaya devam etmektedir. Kuruluşunuz için en iyi yaklaşımı seçmek üzere özel ihtiyaçlarınızı ve gereksinimlerinizi dikkatlice değerlendirin.